//package com.fecean.aabbc.netty.client.prod6;
//
//import com.fecean.aabbc.netty.message6.HeartbeatMessage;
//import com.fecean.aabbc.netty.message6.MessageBuilder;
//import com.fecean.aabbc.netty.message6.MessageType;
//import io.netty.channel.ChannelHandler;
//import io.netty.channel.ChannelHandlerContext;
//import io.netty.channel.ChannelInboundHandlerAdapter;
//import io.netty.handler.timeout.IdleState;
//import io.netty.handler.timeout.IdleStateEvent;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//
///**
// ** Netty客户端心跳处理
// *
// * @author: chenfenghai
// * @version: 1.0
// * @date: 2020-03-17 15:59
// * @blame Team
// */
//@Slf4j
//@Component
//@ChannelHandler.Sharable
//public class NettyClientHeartbeatHandler extends ChannelInboundHandlerAdapter {
//
//    /**
//     ** Netty客户端启动器
//     */
//    @Resource
//    NettyClientStarter nettyClientStarter;
//
//    /**
//     ** 影院属性配置
//     */
//    @Resource
//    CinemaConfig cinemaConfig;
//
//    /**
//     ** 心跳计数器
//     */
//    private int idleHeartbeatCount = 0;
//
//    /**
//     ** 心跳重连最大值
//     */
//    private static final int IDLE_HEARTBEAT_MAX_COUNT = 10;
//
//    /**
//     ** 读取数据处理
//     *
//     * @param ctx 通道上下文
//     * @param msg 读取到的数据
//     * @throws Exception 处理过程中存在异常则抛出
//     */
//    @Override
//    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        MessageBuilder messageBuilder = MessageBuilder.of(msg);
//        if(messageBuilder.isMessage(MessageType.HEARTBEAT)){
//            log.info("客户端[{}-{}]收到心跳",
//                    messageBuilder.getMessage().getTenantId(),
//                    messageBuilder.getMessage().getCinemaCode());
//            // 收到心跳响应，重置计数器为0
//            idleHeartbeatCount = 0;
//            return;
//        }
//        ctx.fireChannelRead(msg);
//    }
//
//    /**
//     ** 客户端失去连接处理，重新连接服务器
//     *
//     * @param ctx 通道上下文
//     */
//    @Override
//    public void channelInactive(ChannelHandlerContext ctx) {
//        // 重新连接服务器
//        nettyClientStarter.reconnect();
//    }
//
//    /**
//     ** 心跳机制，事件触发处理，如果N秒内没有读或写操作，则发送心跳信息
//     *
//     * @param ctx 通道上下文
//     * @param evt 心跳事件
//     * @throws Exception 处理过程中存在异常则抛出
//     */
//    @Override
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//        // 不是心跳事件类型，则跳过
//        if (!(evt instanceof IdleStateEvent)) {
//            ctx.fireUserEventTriggered(evt);
//            return;
//        }
//        // 不是读写超时心跳类型，则跳过
//        IdleState state = ((IdleStateEvent) evt).state();
//        if (IdleState.ALL_IDLE.compareTo(state) != 0) {
//            ctx.fireUserEventTriggered(evt);
//            return;
//        }
//        // 心跳计数器超过最大值时，关闭当前netty channel
//        // 触发channelInactive事件，进行重新连接
//        if(idleHeartbeatCount > IDLE_HEARTBEAT_MAX_COUNT){
//            log.info("客户端[{}-{}]心跳超过最大值[{}]，将进行重新连接",
//                    cinemaConfig.getTenantId(), cinemaConfig.getCinemaCode(), idleHeartbeatCount);
//            ctx.channel().close();
//            return;
//        }
//        // 发送心跳信息
//        HeartbeatMessage message = MessageBuilder.buildHeartbeatMessage(
//                cinemaConfig.getTenantId(), cinemaConfig.getCinemaCode());
//        ctx.writeAndFlush(message.toDataObject());
//        // 心跳计数器加一
//        idleHeartbeatCount++;
//        ctx.fireUserEventTriggered(evt);
//    }
//
//    /**
//     ** 报错 处理事件
//     *
//     * @param ctx 通道上下文
//     * @param cause 异常
//     * @throws Exception 处理过程中存在异常则抛出
//     */
//    @Override
//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        log.error("", cause);
//        ctx.fireExceptionCaught(cause);
//    }
//}
